home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Reference Guide
/
C-C++ Interactive Reference Guide.iso
/
c_ref
/
csource5
/
316_01
/
as8.c
< prev
next >
Wrap
Text File
|
1990-05-16
|
32KB
|
1,683 lines
/*
* z8 assembler hgw july 1983: h.-g. willers
*
* register syntax:
* register: r0 - r127, r240 - r255
* working register: w0 - w15
*
*/
#include <stdio.h>
#include <setjmp.h>
#define NCPS 33 /* number of characters per symbol */
#define NCPLE NCPS+2 /* number of characters per listing element */
#define NLEPL 1 /* number of listing elements per line */
#define NBIN 32
#define NTSYM 512 /* length of numeric-label table */
#define NERR 10
#define NINPUT 128
#define NCODE 128
#define NTIT 64
#define HASHSIZ 503 /* hashtable size */
/* must be prime */
/* more primes: */
/* 503, 607, 701, 809, 907, 1009 */
/* see: handbook of math. functions p. 879 */
#define NLIST 0
#define SLIST 1
#define ALIST 2
#define CLIST 3
typedef unsigned addr_t;
struct sym
{
char *s_name;
char s_type;
char s_flag;
addr_t s_addr;
};
#define S_UND 0
#define S_ABS 1
#define S_OP0 2
#define S_OP2 4
#define S_OP3 5
#define S_OP4 6
#define S_OP5 7
#define S_OP6 8
#define S_OP7 9
#define S_OP8 10
#define S_OP9 11
#define S_OP10 12
#define S_OP11 13
#define S_OP12 14
#define S_OP13 15
#define S_OP14 16
#define S_OP15 17
#define S_LIT 19
#define S_REG 20
#define S_WREG 21
#define S_IR 22 /* register indirect */
#define S_WIR 23 /* working register indirect */
#define S_INDEX 24
#define S_WORD 25
#define S_ASCII 26
#define S_ASCIZ 27
#define S_BLKB 28
#define S_PAGE 29
#define S_TITLE 30
#define S_BYTE 31
#define S_HLIST 32
#define S_OLIST 33
#define S_INTEL 34
#define S_MKBUG 35
#define S_LIST 36
#define S_NLIST 37
#define S_START 38
#define WRMASK 0xe0 /* msbs for working reg. add. */
#define CALL 0xd6 /* direct call */
#define CALLI 0xd4 /* indirect call */
#define SOB 0x0a /* sob-instruction */
#define JUMP 0x8d /* jump-always instruction */
#define JUMPI 0x30 /* jump indirect */
#define SRP 0x31
#define INCW 0x0e /* inc working register */
#define S_MDF 01 /* Mult. def */
#define S_ASG 02 /* Assigned def */
struct tsym
{
int t_num;
addr_t t_addr;
};
struct tsymp
{
struct tsym *t_fp;
struct tsym *t_bp;
};
struct addr
{
char a_type;
char a_reg;
addr_t a_addr;
};
int line;
int page;
int lop;
int pass;
int ntsym;
int sflag = 0; /* symbol-table-flag */
int lflag;
int nflag;
int eflag;
addr_t laddr;
int lmode;
int ldis = 0; /* listing disable */
/* =1 listing is disabled */
int hlist = 1; /* hex listing is default */
int ninst = 0; /* number of installs into symbol table */
char *ep;
char eb[NERR];
char *ip;
char ib[NINPUT];
char *cp;
char cb[NCODE];
char tb[NTIT];
int bo;
int ba;
char bb[NBIN];
unsigned int startadr = 0xffff; /* start address */
char liname[80];
char obname[80]; /* listing and object filenames */
char stbnam[80];
jmp_buf env;
long daytime;
long time();
char *ctime();
char *malloc();
struct sym *lookup();
struct sym *addr1();
struct sym *dot; /* pointer to . value into symbol table */
struct sym sym[HASHSIZ] = {0}; /* space for symbol table */
extern struct sym optab[];
struct tsym tsym[NTSYM];
struct tsymp tsymp[10];
/* lower opcode nibbles for class-8 opcodes */
/* ordered as follows: destination, source, nibble */
/* table ends at zero destination */
char c8nib[] = { S_WREG, S_WREG, 2,
S_WREG, S_WIR, 3,
S_WREG, S_WREG, 4,
S_WREG, S_REG, 4,
S_REG, S_WREG, 4,
S_REG, S_REG, 4,
S_WREG, S_WIR, 5,
S_WREG, S_IR, 5,
S_REG, S_WIR, 5,
S_REG, S_IR, 5,
S_WREG, S_LIT, 6,
S_REG, S_LIT, 6,
S_WIR, S_LIT, 7,
S_IR, S_LIT, 7,
0, 0, 0
};
char movtab[] = { S_WREG, S_LIT, 0x0c,
S_WREG, S_REG, 0x08,
S_WREG, S_WREG, 0x08,
S_REG, S_WREG, 0x09,
S_WREG, S_INDEX, 0xc7,
S_INDEX, S_WREG, 0xd7,
S_WREG, S_WIR, 0xe3,
S_WIR, S_WREG, 0xf3,
S_REG, S_REG, 0xe4,
S_REG, S_IR, 0xe5,
S_REG, S_LIT, 0xe6,
S_IR, S_LIT, 0xe7,
S_IR, S_REG, 0xf5,
S_WIR, S_REG, 0xf5,
S_IR, S_WREG, 0xf5,
S_WIR, S_WREG, 0xf5,
0, 0, 0
};
char c13tab[] = {S_WREG, S_WIR, 1,
S_WIR, S_WREG, 2,
0, 0, 0
};
FILE *lfp;
FILE *ofp;
FILE *sfp;
char *strrchr();
char *strchr();
main(argc, argv)
char *argv[];
{
register char *p;
register c, i;
struct tsym *tp;
char *iptr; /* index-pointer */
char *fn;
FILE *afile();
fn = NULL;
for (i=1; i<argc; ++i) {
p = argv[i];
if (*p == '-') {
++p;
while (c = *p++)
switch(c) {
case 'l':
case 'L':
++lflag;
break;
case 'n':
case 'N':
++nflag;
break;
default:
fprintf(stderr, "%c: ignored.\n", c);
}
} else
fn = p;
}
if (fn != NULL) {
sfp = afile(fn, 0);
if((iptr = strrchr(fn, '/')) == NULL)
strcpy(liname, fn);
else
strcpy(liname, ++iptr);
if((iptr = strrchr(liname, '.')) != NULL)
*iptr = 0; /* truncate suffix (if any) */
if (!nflag) {
strcpy(obname, liname);
strcat(obname, ".o");
}
if (lflag) {
strcat(liname, ".l");
lfp = afile(liname, 1);
}
if(strcmp (fn, obname) == 0) {
fprintf(stderr, "Would overwrite %s\n", fn);
exit(1);
}
ofp = afile(obname, 1);
for (pass=0; pass<2; ++pass) {
if(pass == 0)
insopc(); /* install opcodes */
dot = lookup(".", 0, 0); /* locate . in table */
dot->s_type = S_ABS;
dot->s_flag = S_ASG;
dot->s_addr = 0;
line = 0;
page = 1;
lop = 60;
if (pass == 1) {
rewind(sfp);
for (i=0; i<10; ++i) {
tsymp[i].t_fp = NULL;
tsymp[i].t_bp = NULL;
tp = tsym;
while (tp < &tsym[ntsym]) {
if (tp->t_num == i) {
tsymp[i].t_fp = tp;
break;
}
++tp;
}
}
}
while (fgets(ib, sizeof ib, sfp) != NULL) {
iptr = strchr(ib,'\n');
*iptr = 0;
++line;
cp = cb;
ep = eb;
ip = ib;
eflag = 0;
setjmp(env);
if (eflag == 0)
xasm();
if (pass == 1) {
diag();
list();
}
}
}
if (!nflag) {
bflush();
beof();
}
prstb();
prstat();
}
}
FILE *
afile(fn, wf)
char *fn;
{
register FILE *fp;
fp = fopen(fn, wf?"w":"r");
if (fp == NULL) {
fprintf(stderr, "%s: cannot open.\n", fn);
exit(1);
}
return (fp);
}
xasm()
{
register c;
register addr_t a;
struct sym *sp;
struct tsym *tp;
int b, d, op;
char *p, id[NCPS];
struct addr a1, a2;
laddr = dot->s_addr;
lmode = SLIST;
loop:
while ((c = getnb()) == ';')
;
if (c == 0 || c == '/')
return;
if (isdigit(c)) {
if (getnb() != ':')
err('q');
c -= '0';
if (pass == 0) {
if (ntsym >= NTSYM)
error("Too many temp. symbols!\n");
tsym[ntsym].t_num = c;
tsym[ntsym].t_addr = dot->s_addr;
++ntsym;
}
else {
tp = tsymp[c].t_fp;
tsymp[c].t_bp = tp;
tsymp[c].t_fp = NULL;
++tp;
while (tp < &tsym[ntsym]) {
if (tp->t_num == c) {
tsymp[c].t_fp = tp;
break;
}
++tp;
}
}
goto loop;
}
if (!isidc(c))
err('q');
getid(c, id);
if ((c = getnb()) == ':') {
sp = lookup(id, 1, 0);
if (pass == 0) {
if (sp->s_type!=S_UND && (sp->s_flag&S_ASG)==0)
sp->s_flag |= S_MDF;
sp->s_type = S_ABS;
sp->s_addr = dot->s_addr;
} else {
if ((sp->s_flag&S_MDF) != 0)
err('m');
if (sp->s_type!=S_ABS || sp->s_addr!=dot->s_addr)
err('p');
}
lmode = ALIST;
goto loop;
}
if (c == '=') {
sp = lookup(id, 1, 0);
if (sp->s_type!=S_UND && (sp->s_flag&S_ASG)==0)
err('m');
expr(&a1);
sp->s_addr = laddr = a1.a_addr;
sp->s_flag = S_ASG;
sp->s_type = a1.a_type;
lmode = ALIST;
goto loop;
}
unget(c);
lmode = CLIST;
if ((sp=lookup(id, 0, 0)) == NULL) {
err('o');
return;
}
op = sp->s_addr;
switch(sp->s_type) {
case S_HLIST:
case S_OLIST:
hlist = op;
lmode = SLIST;
break;
case S_LIST:
ldis = 0;
break;
case S_NLIST:
ldis = 1;
break;
case S_BYTE:
case S_WORD:
do {
expr(&a1);
a = a1.a_addr;
if (sp->s_type == S_BYTE) {
bcheck(a, 't');
outb(a);
} else
outw(a);
} while ((c = getnb()) == ',');
unget(c);
break;
case S_ASCII:
case S_ASCIZ:
if ((d = getnb()) == 0)
err('q');
while ((c = get()) != 0 && c != d)
outb(c);
if (c == 0)
err('q');
if (sp->s_type == S_ASCIZ)
outb(0);
break;
case S_BLKB:
expr(&a1);
a = a1.a_addr;
if ((c = getnb()) == ',') {
expr(&a1);
b = a1.a_addr;
} else {
unget(c);
b = 0;
}
while (a--)
outb(b);
lmode = ALIST;
break;
case S_TITLE:
p = tb;
if (c = getnb()) {
do {
if (p < &tb[NTIT-1])
*p++ = c;
} while (c = get());
}
*p = 0;
unget(c);
case S_PAGE:
lop = 60;
lmode = NLIST;
break;
case S_START:
expr(&a1);
startadr = a1.a_addr;
break;
case S_OP0:
outb(op);
break;
case S_OP2:
addr(&a1);
if(a1.a_type == S_LIT) {
a = a1.a_addr; /* only banks 0 - 7 */
if((0 <= a) && (a < 128)) {
if(a % 16) aerr();
else {
outb(SRP); outb(a);
break;
}
}
}
aerr();
break;
case S_OP3:
addr(&a1);
if(a1.a_type == S_REG) {
outb(op);
outb(a1.a_addr);
break;
}
if(a1.a_type == S_WREG) {
outb(op);
outb(a1.a_addr | WRMASK);
break;
}
if(a1.a_type == S_IR) {
outb(op + 1);
outb(a1.a_addr);
break;
}
if(a1.a_type == S_WIR) {
outb(op + 1);
outb(a1.a_addr | WRMASK);
break;
}
aerr();
break;
case S_OP4:
addr(&a1);
if(a1.a_type == S_ABS) {
outb(CALL);
outw(a1.a_addr);
break;
}
if(a1.a_type == S_IR) {
a = a1.a_addr;
even(a);
outb(CALLI);
outb(a);
break;
}
if(a1.a_type == S_WIR) {
a = a1.a_addr;
even(a);
outb(CALLI);
outb(a | WRMASK);
break;
}
aerr();
break;
case S_OP5:
addr(&a1);
if(a1.a_type == S_ABS ) {
outb(op);
outw(a1.a_addr);
break;
}
if(a1.a_type == S_IR) {
if(op != JUMP) aerr();
outb(JUMPI);
a = a1.a_addr;
even(a);
outb(a);
break;
}
if(a1.a_type == S_WIR) {
if(op != JUMP) aerr();
outb(JUMPI);
a = (a1.a_addr | WRMASK);
even(a);
outb(a);
break;
}
aerr();
break;
case S_OP7:
addr(&a1);
if(a1.a_type == S_WREG)
op |= (a1.a_addr << 4);
else
aerr();
comma();
case S_OP6:
expr(&a1);
a = a1.a_addr - dot->s_addr - 2;
bcheck(a, 'a');
outb(op);
outb(a);
break;
case S_OP8:
addr(&a1);
comma();
addr(&a2);
if((a = check(a1.a_type, a2.a_type, c8nib)) == 0) {
aerr();
break;
}
op |= a; /* mask in lower opcode nibble */
if((a1.a_type == S_WREG) && (a2.a_type == S_WREG)) {
outb(op);
outb(a1.a_addr | ((a2.a_addr) << 4));
break;
}
if((a1.a_type == S_WIR) && (a2.a_type == S_WREG)) {
outb(op);
outb(a1.a_addr | ((a2.a_addr) << 4));
break;
}
if(a1.a_type == S_LIT) {
outb(op);
if((a2.a_type == S_WREG) || (a2.a_type == S_WIR))
outb(a2.a_addr | WRMASK);
else
outb(a2.a_addr);
outb(a1.a_addr); /* immediate value */
break;
}
outb(op);
if((a1.a_type == S_WREG) || (a1.a_type == S_WIR))
outb(a1.a_addr | WRMASK);
else
outb(a1.a_addr);
if((a2.a_type == S_WREG) || (a2.a_type == S_WIR))
outb(a2.a_addr | WRMASK);
else
outb(a2.a_addr);
break;
case S_OP9:
addr(&a1);
comma();
addr(&a2);
if((a = check(a1.a_type, a2.a_type, movtab)) > 0) {
if(a < 20) {
if(a2.a_type == S_WREG) {
op = a | (a2.a_addr << 4);
a = a1.a_addr;
if(a1.a_type == S_WREG)
a |= WRMASK;
}
else {
op = a | (a1.a_addr << 4);
a = a2.a_addr;
if(a2.a_type == S_WREG)
a |= WRMASK;
}
outb(op); outb(a); break;
}
switch(a & 0377) {
case 0xc7:
b = a1.a_addr | (a2.a_addr << 4);
d = a1.a_reg;
break;
case 0xd7:
b = a2.a_addr | (a1.a_addr << 4);
d = a2.a_reg;
break;
case 0xe3:
case 0xf3:
b = a1.a_addr | (a2.a_addr << 4);
d = 10000;
break;
case 0xe4:
case 0xe5:
case 0xf5:
if((a1.a_type == S_WIR) || (a1.a_type == S_WREG))
b = a1.a_addr | WRMASK;
else
b = a1.a_addr;
if((a2.a_type == S_WIR) || (a2.a_type == S_WREG))
d = a2.a_addr | WRMASK;
else
d = a2.a_addr;
break;
case 0xe6:
case 0xe7:
if((a2.a_type == S_WIR) || (a2.a_type == S_WREG))
b = a2.a_addr | WRMASK;
else
b = a2.a_addr;
d = a1.a_addr;
break;
}
outb(a); outb(b);
if(d != 10000) outb(d);
break;
}
else
aerr();
break;
case S_OP10:
addr(&a1);
if(a1.a_type == S_WREG) {
even(a1.a_addr);
outb(op);
outb(a1.a_addr | WRMASK);
break;
}
if(a1.a_type == S_REG) {
even(a1.a_addr);
outb(op); outb(a1.a_addr);
break;
}
if(a1.a_type == S_WIR) {
outb(op + 1);
outb(a1.a_addr | WRMASK);
break;
}
if(a1.a_type == S_IR) {
outb(op + 1);
outb(a1.a_addr);
break;
}
aerr();
break;
case S_OP11:
case S_OP12:
addr(&a1);
if(a1.a_type == S_WREG) {
if(sp->s_type == S_OP11) {
outb(INCW | (a1.a_addr << 4));
break;
}
else {
outb(op);
outb(a1.a_addr | WRMASK);
break;
}
}
if(a1.a_type == S_REG) {
outb(op);
outb(a1.a_addr);
break;
}
if(a1.a_type == S_WIR) {
outb(op + 1);
outb(a1.a_addr | WRMASK);
break;
}
if(a1.a_type == S_IR) {
outb(op + 1);
outb(a1.a_addr);
break;
}
aerr();
break;
case S_OP13:
addr(&a1);
comma();
addr(&a2);
if((a = check(a1.a_type, a2.a_type, c13tab)) > 0) {
if(a == 1)
outb(sp->s_flag);
else
outb(sp->s_addr);
if (a1.a_type == S_WREG)
outb(a2.a_addr | (a1.a_addr << 4));
else
outb(a1.a_addr | (a2.a_addr << 4));
break;
}
else {
aerr();
break;
}
case S_OP14:
case S_OP15:
addr(&a1);
comma();
addr(&a2);
if((a1.a_type == S_WIR) && (a2.a_type == S_WIR)) {
outb(op);
outb(a1.a_addr | (a2.a_addr << 4));
break;
}
aerr();
break;
default:
err('o');
}
goto loop;
}
check(source, dest, table)
register char dest, source;
char *table;
{ register char *ptr;
ptr = table; /* get address of legal var. table */
while(*ptr != 0) {
if(*ptr++ == dest ) {
if(*ptr++ == source)
return(*ptr); /* return nibble */
else
ptr++;
}
else {
ptr++; ptr++;
}
}
return(0); /* not found */
}
/* check for even argument */
even(arg)
int arg;
{ if(arg & 1) err('e'); }
addr(ap)
register struct addr *ap;
{ register int c, n;
register addr_t;
register struct sym *sp;
char id[NCPS];
if((c = getnb()) == '$') {
expr(ap);
if ((ap->a_type != S_UND) && (ap->a_type != S_ABS))
aerr();
ap->a_type = S_LIT;
return;
}
if(c == '(') {
if(isidc(c = getnb())) {
getid(c, id);
if(getnb() != ')') err('q');
if(chkreg(ap, id) > 0) {
if(ap->a_type == S_REG) {
ap->a_type = S_IR;
return;
}
if(ap->a_type == S_WREG) {
ap->a_type = S_WIR;
return;
}
err('q');
}
else {
sp = lookup(id, 0, 0);
if(sp == NULL) {
err('u');
return;
}
else {
if(sp->s_type == S_REG) {
ap->a_type = S_IR;
ap->a_addr = sp->s_addr;
return;
}
if(sp->s_type == S_WREG) {
ap->a_type = S_WIR;
ap->a_addr = sp->s_addr;
return;
}
err('q');
return;
}
}
}
else
err('q');
}
unget(c);
expr(ap);
if(ap->a_type != S_REG)
return;
if((c = getnb()) != '(') {
unget(c);
return;
}
/* for indexed addressing a_addr contains index part */
/* a_reg contains offset part */
if(isidc(c = getnb())) {
getid(c, id);
if(getnb() != ')') err('q');
n = ap->a_addr; /* save offset */
if(chkreg(ap, id) > 0) {
if(ap->a_type == S_WREG) {
ap->a_type = S_INDEX;
ap->a_reg = n;
return;
}
err('q');
}
else {
sp = lookup(id, 0, 0);
if(sp == NULL) {
err('u');
return;
}
else {
if(sp->s_type == S_WREG) {
ap->a_type = S_INDEX;
ap->a_addr = sp->s_addr;
ap->a_reg = n;
return;
}
err('q');
}
}
}
else
err('Q');
return;
}
expr(ap)
register struct addr *ap;
{
register int c;
struct addr right;
term(ap);
if (ap->a_type != S_ABS)
return;
for (;;) {
c = getnb();
if ((c=='<' || c=='>') && c!=getnb())
err('q');
if (!any(c, "+-*%&|><^")) {
unget(c);
break;
}
term(&right);
if (right.a_type != S_ABS)
err('r');
switch(c) {
case '+':
ap->a_addr += right.a_addr;
break;
case '-':
ap->a_addr -= right.a_addr;
break;
case '*':
ap->a_addr *= right.a_addr;
break;
case '%':
ap->a_addr /= right.a_addr;
break;
case '&':
ap->a_addr &= right.a_addr;
break;
case '|':
ap->a_addr |= right.a_addr;
break;
case '^':
ap->a_addr ^= right.a_addr; /* xor */
break;
case '>':
ap->a_addr >>= right.a_addr;
break;
case '<':
ap->a_addr <<= right.a_addr;
}
}
}
term(ap)
register struct addr *ap;
{
register int c;
register int n, r, v;
char id[NCPS];
register struct sym *sp;
register struct tsym *tp;
c = getnb();
if (c == '[') {
expr(ap);
if (getnb() != ']')
err('q');
return;
}
/* added literal hgw */
if (c == '\'') {
c = get();
c = c&0177;
ap->a_type = S_ABS;
ap->a_addr = c;
return;
}
/* operator-precedence of unary operators changed [hgw] */
if (c == '-' || c == '!') {
term(ap);
if (ap->a_type != S_ABS) {
err('r');
ap->a_type = S_ABS;
}
if (c == '-')
ap->a_addr = -ap->a_addr;
else
ap->a_addr = ~ap->a_addr;
return;
}
if (isdigit(c)) {
ap->a_type = S_ABS;
r = 10;
if (c == '0') {
r = 8;
if ((c = get()) == 'x') {
r = 16;
c = get();
}
else
if (c == 'B') {
r = 2;
c = get();
}
}
n = 0;
while ((v = digit(c, r)) >= 0) {
n = r*n + v;
c = get();
}
if (c=='f' || c=='b') {
if ((n < 10) && (n >= 0)) {
if (c == 'f')
tp = tsymp[n].t_fp; else
tp = tsymp[n].t_bp;
if (tp != NULL) {
ap->a_addr = tp->t_addr;
return;
}
}
err('u');
ap->a_addr = 0;
return;
}
unget(c);
ap->a_addr = n;
return;
}
if (isidc(c)) {
getid(c, id);
if(chkreg(ap, id) > 0 ) return;
if ((sp = lookup(id, 0, 0)) != NULL) {
ap->a_type = sp->s_type;
ap->a_addr = sp->s_addr;
return;
}
err('u');
ap->a_type = S_ABS;
ap->a_addr = 0;
return;
}
err('q');
}
/* check for register usage */
/* w must be in the range 0 - 15 */
/* r must be in the range 0 - 127, or 240 - 255 */
/* if a valid register, set type in the supplied structure */
/* and return +1 */
/* otherwise return 0 */
chkreg(ap, id)
register struct addr *ap;
char *id;
{
register char *ptr;
register int n;
ptr = id; /* get address of token */
if(*ptr == 'w') {
n = getnum(ptr, 2); /* 2 digits max */
if((0 <= n) && (n < 16)) {
ap->a_type = S_WREG; /* short */
ap->a_addr = n;
return(1);
}
}
if(*ptr == 'r') {
n = getnum(ptr, 3); /* 3 digits max */
if(((0 <= n) && (n < 128)) || ((240 <= n) && (n < 256))) {
ap->a_type = S_REG; /* long */
ap->a_addr = n;
return(1);
}
}
return(0);
}
/* get number of working register */
getnum(str, nmax)
char *str;
int nmax;
{
register int n, c, i;
register int imax;
register char *ptr;
ptr = str;
imax = nmax;
ptr++; /* skip leading 'w', 'r' or 'R' */
n = i = 0;
while((i < imax) && ((c = *ptr++) != '\0')) {
n = 10 * n + c - '0';
i++;
}
if((i == imax) && (*ptr != '\0')) return(-1); /* since no '\0' reached */
else return(n);
}
digit(c, r)
register c, r;
{
if (r == 16) {
if (c >= 'A' && c <= 'F')
return (c - 'A' + 10);
if (c >= 'a' && c <= 'f')
return (c - 'a' + 10);
}
if (r == 8) {
if (c >= '0' && c <= '7')
return (c - '0');
else
return (-1);
}
if (r == 2) {
if (c >= '0' && c <= '1')
return (c - '0');
else
return (-1);
}
if (c >= '0' && c <= '9')
return (c - '0');
return (-1);
}
any(c, s)
register c;
register char *s;
{
register char b;
while (b = *s++)
if (b == c)
return (1);
return (0);
}
list()
{
register char *wp;
register nb;
if (lfp==NULL || lmode==NLIST || ldis==1)
return;
slew();
while (ep < &eb[NERR])
*ep++ = ' ';
fprintf(lfp, "%.10s", eb);
if (lmode == SLIST) {
fprintf(lfp, "%24s%5d %s\n", "", line, ib);
return;
}
fprintf(lfp, hlist?" %04x":" %06o", laddr);
if (lmode == ALIST) {
fprintf(lfp, "%17s%5d %s\n", "", line, ib);
return;
}
wp = cb;
nb = cp - cb;
list1(wp, nb, 1);
fprintf(lfp, " %5d %s\n", line, ib);
while ((nb -= 4) > 0) {
wp += 4;
slew();
fprintf(lfp, "%17s", "");
list1(wp, nb, 0);
putc('\n', lfp);
}
}
list1(wp, nb, f)
register char *wp;
register nb;
{
register i;
if (nb > 4)
nb = 4;
for (i=0; i<nb; ++i)
fprintf(lfp, hlist?" %02x":" %03o", (*wp++)&0377);
if (f)
while (i < 4) {
fprintf(lfp, " ");
++i;
}
}
slew()
{
if(lfp == NULL)
return;
if (lop++ >= 60) {
daytime = time(NULL);
if (page != 1 ) /* suppress form-feed on 1st page */
fprintf(lfp, "\f");
fprintf(lfp, "Z8 Assembler: h.-g. willers\tpage %d\t\t%s", page++, ctime(&daytime));
fprintf(lfp, "%s\n\n", tb);
lop = 4;
}
}
/* print symbol table */
prstb()
{
register struct sym *sp;
register char *p1;
register char ochar;
register int i, j;
int cntr;
if(!lflag) return;
if(lflag) {
lop = 60; /* force new page */
slew();
fprintf(lfp, "Symboltable dump\n\n");
}
sp = &sym[0]; /* get pointer to begin of symbol table */
/* remove any item not assigned or label */
for(i= 0; i < HASHSIZ; i++) {
p1 = sp->s_name;
if(p1 != 0) {
if(sp->s_type != S_ABS)
if(sp->s_flag != S_ASG)
sp->s_name = 0;
}
sp++;
}
dot->s_name = 0; /* remove '.' */
cntr = 0;
sp = &sym[0];
for(i=0; i < HASHSIZ; i++) {
p1 = sp->s_name;
if(p1 == 0) sp++;
else {
if(cntr != 0)
fprintf(lfp, " ");
j = 0;
while(j < (NCPS - 1)) {
j++;
if((ochar = *p1++) != '\0')
fprintf(lfp,"%c", ochar);
else {
fprintf(lfp,"%c", ' ');
break;
}
}
while(j < NCPLE) {
j++;
fprintf(lfp, "%c", ' ');
}
j = sp->s_addr;
fprintf(lfp, hlist?" %04x":"%06o", j);
cntr++;
if(cntr == NLEPL) {
cntr = 0;
fprintf(lfp,"\n");
slew();
}
sp++;
}
}
fprintf(lfp, "\n");
slew();
}
/* print assembler statistics */
prstat()
{
register int i;
if(!lflag)
return;
if(lop > 50) /* force new page if neccesary */
lop = 60;
slew();
i = HASHSIZ;
fprintf(lfp, "\n\n symboltable-size is %d ; %d entries used\n", i, ninst);
}
bcheck(n, f)
register n;
{
if((n < -128 || n > 127) && ((n & ~(0xff)) != 0))
err(f);
}
comma()
{
if (getnb() != ',')
err('q');
}
getid(c, id)
register c;
char *id;
{
register char *p;
p = id;
do {
if (p < ((&id[NCPS]) - 1))
*p++ = c;
} while (isidc(c=get()) || c=='\'' || (c>='0' && c<='9'));
unget(c);
while (p < &id[NCPS])
*p++ = 0;
}
getnb()
{
register c;
while ((c=get())==' ' || c=='\t')
;
return (c);
}
get()
{
register c;
if ((c = *ip) != '\0')
++ip;
return (c);
}
unget(c)
{
if (c != '\0')
--ip;
}
isdigit(c)
register c;
{
return (c>='0' && c<='9');
}
isidc(c)
register c;
{
if (c == '_')
return (1);
if (c == '.')
return (1);
if (c>='a' && c<='z')
return (1);
if (c>='A' && c<='Z')
return (1);
return (0);
}
struct sym *
lookup(id, f, x)
char *id;
{
register struct sym *sp;
register char *p1, *p2;
register int fihash, lasthash, i;
lasthash = fihash = hash(id);
for(i = 0; i < HASHSIZ; i++) {
sp = &sym[lasthash];
p1 = id;
p2 = sp->s_name;
if(p2 == 0) break; /* found free entry */
else {
if(strncmp(p1,p2,NCPS) != 0) {
lasthash += fihash;
lasthash %= HASHSIZ;
}
else return(sp);
}
}
if (f == 0)
return (NULL);
if(i == HASHSIZ)
error("Too many symbols!\n");
ninst++; /* increment # of install in table */
if(x == 1)
sp->s_name = id;
else {
p2 = malloc((strlen(id) + 1));
sp->s_name = p2;
p1 = id;
strcpy(p2, p1);
}
sp->s_type = S_UND;
sp->s_flag = 0;
sp->s_addr = 0;
return (sp);
}
/* compute hashindex of string */
hash(str)
char *str;
{
register unsigned int i;
register char c;
i = 0;
while((c = *str++) != 0)
i += ( (int) c) & 0377;
i %= HASHSIZ;
if(i == 0 )
i++; /* since we use 'add the hash rehash' */
return(i);
}
aerr()
{
err('a');
}
err(c)
register c;
{
register char *p;
p = eb;
while (p < ep)
if (c == *p++)
return;
if (p < &eb[NERR]) {
*p++ = c;
ep = p;
}
if (c == 'q') {
++eflag;
longjmp(env, 0);
}
}
error(str)
char *str;
{ fprintf(stderr, str);}
diag()
{
register char *p;
p = eb;
while (p < ep)
printf("%c %04d %s\n", *p++, line, ib);
}
outw(w)
register w;
{
outb(w>>8);
outb(w);
}
outb(b)
register b;
{
if (pass != 0) {
if (cp >= &cb[NCODE])
err('z');
else
*cp++ = b;
if (!nflag) {
if (bo>=NBIN || ba+bo!=dot->s_addr) {
bflush();
ba = dot->s_addr;
bo = 0;
}
bb[bo++] = b;
}
}
++dot->s_addr;
}
bflush()
{
register b, c, i;
if (bo == 0)
return;
fprintf(ofp, ":%02x%04x00", bo, ba);
c = bo + ba + (ba>>8);
for (i=0; i<bo; ++i) {
b = bb[i]&0377;
fprintf(ofp, "%02x", b);
c += b;
}
fprintf(ofp, "%02x\n", (-c)&0377);
}
beof()
{
register int dummy;
dummy = ((startadr & 0377) + (startadr >> 8) + 1) & 0377;
dummy = -dummy & 0377;
if (startadr == 0xffff) /* not given */
fprintf(ofp, ":0000000000\n");
else
fprintf(ofp, ":00%04x01%02x\n", startadr, dummy);
}
/*
* install z8 opcodes
*/
insopc()
{
register struct sym *sp;
register struct sym *pp;
for (sp = optab;;) {
if (*(sp->s_name) == 0)
return;
pp = lookup(sp->s_name, 1, 1);
if(pp == NULL) {
fprintf(stderr,"hashtable-error with symbol: %s\n", sp->s_name);
exit(1);
}
pp->s_type = sp->s_type;
pp->s_flag = sp->s_flag;
pp->s_addr = sp->s_addr;
sp++;
}
}
struct sym optab[] = {
".", S_ABS, S_ASG, 0,
".byte", S_BYTE, 0, 0,
".word", S_WORD, 0, 0,
".ascii", S_ASCII, 0, 0,
".asciz", S_ASCIZ, 0, 0,
".blkb", S_BLKB, 0, 0,
".page", S_PAGE, 0, 0,
".title", S_TITLE, 0, 0,
".hlist", S_HLIST, 0, 1,
".olist", S_OLIST, 0, 0,
".list", S_LIST, 0, 0,
".nlist", S_NLIST, 0, 0,
".end", S_START, 0, 0,
"ccf", S_OP0, 0, 0xef,
"di", S_OP0, 0, 0x8f,
"ei", S_OP0, 0, 0x9f,
"reti", S_OP0, 0, 0xbf,
"nop", S_OP0, 0, 0xff,
"rcf", S_OP0, 0, 0xcf,
"ret", S_OP0, 0, 0xaf,
"scf", S_OP0, 0, 0xdf,
"srp", S_OP2, 0, 0x31,
"clr", S_OP3, 0, 0xb0,
"com", S_OP3, 0, 0x60,
"da", S_OP3, 0, 0x40,
"dec", S_OP3, 0, 0,
"pop", S_OP3, 0, 0x50,
"push", S_OP3, 0, 0x70,
"rl", S_OP3, 0, 0x90,
"rlc", S_OP3, 0, 0x10,
"rr", S_OP3, 0, 0xe0,
"rrc", S_OP3, 0, 0xc0,
"sra", S_OP3, 0, 0xd0,
"swap", S_OP3, 0, 0xf0,
"call", S_OP4, 0, 0,
"jmp", S_OP5, 0, 0x8d,
"jcs", S_OP5, 0, 0x7d,
"jcc", S_OP5, 0, 0xfd,
"jeq", S_OP5, 0, 0x6d,
"jne", S_OP5, 0, 0xed,
"jpl", S_OP5, 0, 0xdd,
"jmi", S_OP5, 0, 0x5d,
"jov", S_OP5, 0, 0x4d,
"jnov", S_OP5, 0, 0xcd,
"jge", S_OP5, 0, 0x9d,
"jlt", S_OP5, 0, 0x1d,
"jgt", S_OP5, 0, 0xad,
"jle", S_OP5, 0, 0x2d,
"juge", S_OP5, 0, 0xfd,
"jult", S_OP5, 0, 0x7d,
"jugt", S_OP5, 0, 0xbd,
"jule", S_OP5, 0, 0x3d,
"br", S_OP6, 0, 0x8b,
"bcs", S_OP6, 0, 0x7b,
"bcc", S_OP6, 0, 0xfb,
"beq", S_OP6, 0, 0x6b,
"bne", S_OP6, 0, 0xeb,
"bpl", S_OP6, 0, 0xdb,
"bmi", S_OP6, 0, 0x5b,
"bov", S_OP6, 0, 0x4b,
"bnov", S_OP6, 0, 0xcb,
"bge", S_OP6, 0, 0x9b,
"blt", S_OP6, 0, 0x1b,
"bgt", S_OP6, 0, 0xab,
"ble", S_OP6, 0, 0x2b,
"buge", S_OP6, 0, 0xfb,
"bult", S_OP6, 0, 0x7b,
"bugt", S_OP6, 0, 0xbb,
"bule", S_OP6, 0, 0x3b,
"sob", S_OP7, 0, 0x0a,
"add", S_OP8, 0, 0x00,
"adc", S_OP8, 0, 0x10,
"sub", S_OP8, 0, 0x20,
"sbc", S_OP8, 0, 0x30,
"or", S_OP8, 0, 0x40,
"and", S_OP8, 0, 0x50,
"tcm", S_OP8, 0, 0x60,
"tm", S_OP8, 0, 0x70,
"cmp", S_OP8, 0, 0xa0,
"xor", S_OP8, 0, 0xb0,
"mov", S_OP9, 0, 0,
"incw", S_OP10, 0, 0xa0,
"decw", S_OP10, 0, 0x80,
"inc", S_OP11, 0, 0x20,
"dec", S_OP12, 0, 0,
/* movp is ldc 'move from/to program memory' */
/* movd is lde 'move from/to data memory' */
/* movpi is ldci 'move from/to prog. mem autoincr.' */
/* movdi is ldei 'move from/to data mem autoincr.' */
/* s_flag contains first line of inst. summary */
/* s_addr contains second line */
"movp", S_OP13, 0xc2, 0xd2,
"movd", S_OP13, 0x82, 0x92,
"movfpi", S_OP14, 0, 0xc3,
"movfdi", S_OP14, 0, 0x83,
"movtpi", S_OP15, 0, 0xd3,
"movtdi", S_OP15, 0, 0x93,
"", 0, 0, 0
};